/*
	Copyright 2009 Benjamin Vedder	vedder87@gmail.com
	
	This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */

package com.google.code.retrobox.editor.dataCollections;

import java.awt.Color;
import java.util.LinkedList;
import java.util.List;

import com.google.code.retrobox.editor.commons.Tools;
import com.google.code.retrobox.editor.tiles.Tile;


public class TileSet {
	private List<TileData> dataList = new LinkedList<TileData>();
	
	private Color[] palette = {	new Color(Integer.parseInt( "000000",16)), 
			new Color(Integer.parseInt( "0000AA",16)),
			new Color(Integer.parseInt( "00AA00",16)),
			new Color(Integer.parseInt( "00AAAA",16)),
			new Color(Integer.parseInt( "AA0000",16)),
			new Color(Integer.parseInt( "AA00AA",16)),
			new Color(Integer.parseInt( "AA5500",16)),
			new Color(Integer.parseInt( "AAAAAA",16)),
			new Color(Integer.parseInt( "555555",16)),
			new Color(Integer.parseInt( "5555FF",16)),
			new Color(Integer.parseInt( "55FF55",16)),
			new Color(Integer.parseInt( "55FFFF",16)),
			new Color(Integer.parseInt( "FF5555",16)),
			new Color(Integer.parseInt( "FF55FF",16)),
			new Color(Integer.parseInt( "FFFF55",16)),
			new Color(Integer.parseInt( "FFFFFF",16))
			};
	
	public TileSet() {
		
	}
	
	/**
	 * Constructor for raw tileset data.
	 * @param tileset
	 * An AVGA hardware-compatible tileset.
	 */
	public TileSet (char[] tileset, char[] colInfo) {
		int hbt = ((Tile.HEIGHT * Tile.WIDTH) / 2);
		char[][] tileArray = new char[tileset.length / hbt][hbt];

		int ind = 0;
		for (int i = 0; i < tileset.length; i += hbt) {
			char[] c = new char[hbt];

			for (int j = 0; j < hbt; j++) {
				
				c[j] = tileset[i + j];
			}

			tileArray[ind] = c;

			ind++;
		}
		
		ind = 0;
		for (char[] pix: tileArray) {
			TileData dta = new TileData(pix, ind);			
			// ----------------- Collision ----------------- //
			dta.collInfo.north = ((colInfo[ind] & 0x01) > 0);
			dta.collInfo.south = ((colInfo[ind] & 0x02) > 0);
			dta.collInfo.west = ((colInfo[ind] & 0x04) > 0);
			dta.collInfo.east = ((colInfo[ind] & 0x08) > 0);
			dta.collInfo.jump = ((colInfo[ind] & 0x10) > 0);
			dta.collInfo.water = ((colInfo[ind] & 0x20) > 0);
			// --------------------------------------------- //			
			
			addTile(dta);
			
			ind++;
			
			if (ind == Tile.MAX_TILES_PER_SET) {
				break;
			}
		}
	}
	
	/**
	 * Constructor to create tileset with empty tiles
	 * @param tiles
	 * the number of empty tiles
	 */
	public TileSet (int tiles) {
		int hbt = ((Tile.HEIGHT * Tile.WIDTH) / 2);
		char[][] tileArray = new char[tiles][hbt];

		int ind = 0;
		for (int i = 0; i < tiles * hbt; i += hbt) {
			char[] c = new char[hbt];

			for (int j = 0; j < hbt; j++) {
				
				c[j] = 0x00;
			}

			tileArray[ind] = c;

			ind++;
		}
		
		ind = 0;
		for (char[] pix: tileArray) {
			TileData dta = new TileData(pix, ind);
			ind++;
			
			addTile(dta);
			
			if (ind == Tile.MAX_TILES_PER_SET) {
				break;
			}
		}
	}
	
	public boolean addTile(TileData data) {
		if (dataList.size() > Tile.MAX_TILES_PER_SET) {
			return false;
		}
		
		data.index = dataList.size();
		dataList.add(data);
		
		return true;
	}
	
	public void addEmptyTiles(int n) {
		int a = dataList.size() + n;
		
		if (a > Tile.MAX_TILES_PER_SET) {
			a = Tile.MAX_TILES_PER_SET;
		}
		
		char[] pix = new char[(Tile.WIDTH * Tile.HEIGHT) / (8 / Tile.TILE_BPP)];
		
		for (char element: pix) {
			element = Tile.DEFAULT_COLOR;
		}
		
		for (int i = dataList.size();i < a;i++) {
			TileData td = new TileData(pix, i);
			dataList.add(td);
		}
	}
	
	public void removeTiles(int n) {
		for (int i = 0;i < n;i++) {
			dataList.remove(dataList.size() - 1);
		}
	}
	
	public TileData getTile(int index) {
		return dataList.get(index);
	}
	
	public List<TileData> getTiles() {
		return dataList;
	}
	
	public int getLength() {
		return dataList.size();
	}
	
	public char[] getRawData() {
		int hbt = ((Tile.HEIGHT * Tile.WIDTH) / 2);
		char[] d = new char[dataList.size() * hbt];
		
		int ind = 0;
		for (TileData element: dataList) {
			for (char element2: element.pixels) {
				d[ind] = element2;
				ind++;
			}
		}
		
		return d;
	}
	
	public char[] getGameduinoRawData() {
		int hbt = ((Tile.HEIGHT * Tile.WIDTH) / 4); // 2 bits per color
		char[] data = new char[dataList.size() * hbt]; // array is tile list size x 16 bytes long
		int[] pal = new int[dataList.size() * 4];
		int counterPal = 0;
		int counterData = 0;
		int ind = 0;
		for (TileData element: dataList) {
			char[] buffer = new char[64];
			int counterBuffer = 0;
			for (char element2: element.pixels) {
				buffer[counterBuffer] = (char) (element2 >>> 4);
				counterBuffer++;
				buffer[counterBuffer] = (char) (element2 & 0x0F);

			}
			//create pallete fill with the first 4 colors found in the image
			int counterPallete = 0;
			counterBuffer = 0;
			int[] locPal = new int[4];
			while(counterPallete < 4 && counterBuffer < 64){
				if(lookupColor(lookupMapColor(buffer[counterBuffer]),locPal) == -1){
					locPal[counterPallete] = lookupMapColor(buffer[counterBuffer]);
					counterPallete++;
				}
				counterBuffer++;
			}
			if(counterPallete < 3){
				for(int t= counterPallete;t < 4; t++){
					locPal[t] = 0x0000;
				}
			}
			for(int t=0; t<4; t++){
				pal[counterPallete] = locPal[t];
				counterPallete++;
			}
			
			counterBuffer = 0;

			//create bytes 00 01 10 01 -> color 0 color 1 color 2 color 1 
			for(int t=0; t < 16;t++){
				char color =(char) (lookupColor(lookupMapColor(buffer[counterBuffer]),pal) << 6 |
				lookupColor(lookupMapColor(buffer[counterBuffer]),pal) << 4 |
				lookupColor(lookupMapColor(buffer[counterBuffer]),pal) << 2 |
				lookupColor(lookupMapColor(buffer[counterBuffer]),pal));
				data[counterData] = color;
				counterData++;
			}
		}
		
		return data; //ToDo export bitdata and pallete
	}
	
	private int lookupMapColor(char color){
		Color c = palette[color];
		return Tools.getColorAsRGB15(c.getRGB());
	}
	
	
	/**
	 * Lookup color in palette buffer
	 * @param color
	 * @param pal
	 * @return
	 */
	private int lookupColor(int color, int[] pal){
		int result = -1;
		for(int t=0;t< 4;t++){
			if(pal[t] == color){
				result = t;
			}
		}
		return 0;
	}
	
	/**
	 * Get data for the collision detector.
	 * @return
	 * Array with collision data. Each tile index from the current tileset
	 * is the same as the corresponding collision byte in the collision array.
	 */
	public char[] getRawCollisionData() {
		char[] data = new char[dataList.size()];
		
		int ind = 0;
		for (TileData element: dataList) {
			char c = 0x00;
			
			if (element.collInfo.north) {
				c = (char)(c | 0x01);
			}
			if (element.collInfo.south) {
				c = (char)(c | 0x02);
			}
			if (element.collInfo.west) {
				c = (char)(c | 0x04);
			}
			if (element.collInfo.east) {
				c = (char)(c | 0x08);
			}
			if (element.collInfo.jump) {
				c = (char)(c | 0x10);
			}
			if (element.collInfo.water) {
				c = (char)(c | 0x20);
			}

			data[ind] = c;
			ind++;
		}
		
		return data;
	}
}














